package p41;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

class MyResource {
     private volatile boolean FLAG = true; // 默认开启，进行生产和消费
     private AtomicInteger atomicInteger = new AtomicInteger();

     BlockingQueue<String> blockingQueue = null;

     // 写，往抽象写，往高处走，查，往细节查，往低处去
     public MyResource(BlockingQueue<String> blockingQueue) {
          this.blockingQueue = blockingQueue;
          System.out.println(blockingQueue.getClass().getName());
     }

     public void myProd() throws Exception {
          String data = null;
          boolean retValue = false;
          while (FLAG) {
               data = atomicInteger.incrementAndGet() + "";
               retValue =  blockingQueue.offer(data, 2L, TimeUnit.SECONDS);
               if (retValue) {
                    System.out.println(Thread.currentThread().getName()
                            + "\t 插入队列成功 " + data + " 成功");
               } else {
                    System.out.println(Thread.currentThread().getName()
                            + "\t 插入队列成功 " + data + " 失败");
               }

               TimeUnit.SECONDS.sleep(1);
          }

          System.out.println(Thread.currentThread().getName()
                  + "\t大老板叫停了，表示FLAG=false，生产活动结束  ");
     }

     public void myConsumer() throws Exception {
          String result = null;
          while (FLAG) {
               result = blockingQueue.poll(2L, TimeUnit.SECONDS);
               if (result == null || "".equalsIgnoreCase(result)) {
                    FLAG = false;
                    System.out.println(Thread.currentThread().getName() +
                            "\t 超过2秒钟没有渠道东西，消费者退出");
                    System.out.println();
                    System.out.println();

                    return;
               }

               System.out.println(Thread.currentThread().getName() +
                       "\t 消费队列 " + result + "成功");
          }
     }

     public void stop() throws Exception {
          this.FLAG = false;
     }
}

/*
由于打印的时候没有加锁，所以顺序可能不一致，但阻塞队列内部逻辑没问题
java.util.concurrent.ArrayBlockingQueue
        Prod	生产者线程启动
        Consumer	消费者线程启动


        Consumer	 消费队列 1成功
        Prod	 插入队列成功 1 成功
        Prod	 插入队列成功 2 成功
        Consumer	 消费队列 2成功
        Prod	 插入队列成功 3 成功
        Consumer	 消费队列 3成功
        Prod	 插入队列成功 4 成功
        Consumer	 消费队列 4成功
        Consumer	 消费队列 5成功
        Prod	 插入队列成功 5 成功



        5秒钟时间到，大老板main线程叫停，活动结束
        Prod	大老板叫停了，表示FLAG=false，生产活动结束
        Consumer	 超过2秒钟没有渠道东西，消费者退出
*/

public class ProdConsumer_BlockQueueDemo {
     public static void main(String[] args) {
          MyResource myResource = new MyResource(
                  new ArrayBlockingQueue<>(10));

          new Thread(()->{
               System.out.println(Thread.currentThread().getName() +
                       "\t生产者线程启动");
               try {
                    myResource.myProd();
               } catch (Exception e) {
                    e.printStackTrace();
               }
          }, "Prod").start();

          new Thread(()->{
               System.out.println(Thread.currentThread().getName() +
                       "\t消费者线程启动");
               System.out.println();
               System.out.println();
               try {
                    myResource.myConsumer();
               } catch (Exception e) {
                    e.printStackTrace();
               }
          }, "Consumer").start();


          try {
               TimeUnit.SECONDS.sleep(5);
               System.out.println();
               System.out.println();
               System.out.println();
               System.out.println("5秒钟时间到，大老板main线程叫停，活动结束");
               myResource.stop();
          } catch (Exception e) {
               e.printStackTrace();
          }
     }
}
